package pl.smath.view.client;

import java.util.Vector;

import gwt.g2d.client.graphics.Surface;
import pl.smath.expression.model.Term;
import pl.smath.expression.parser.ExpressionParser;
import pl.smath.expression.parser.ExpressionParserException;
import pl.smath.view.renderer.TermRenderer;
import pl.smath.view.renderer.TermRendererException;


import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class FractionViewSite {
	private final FlexTable termTable = new FlexTable();
	private final VerticalPanel mainPanel = new VerticalPanel();
	private final HorizontalPanel addPanel = new HorizontalPanel();
	private final TextBox newSymbolTextBox = new TextBox();
	private final Button addTermButton = new Button("Add");
	  
	private final String[] fonts = {"14px sans-serif", "10px serif", "22px venturis"};
	private final String[] fractionExpressions = {"1/2", "y/1024", "2048/2", "-12/x", "(2+2)/2", "1-1/(x+6*y)", "2*1/2+2", "a+1/(1+1/2)", "1+(1-1/(1+1/(1-1/2)))", "1*(x+y/(2*w-1/(1*1/2)))", "(1/2)/((-x)/(2*1/2))", "1-(1/2)/(1/2)+1/(1+1/(1*-x/(y*-z)))*(1+(1/2+x*3/wz-((1+1/x)+1)/5)/2)", "1+x/(1-1/(w*1/(m*n/(a-b/(1*1/(1-c/(x*1/2)))))))", "42+(x*1/2)/(1/15-1/(w*1/(m*n+(15+1/2-3/(4*x))/(a-(b/2*-14)/(1*(2*1/2+4)/(1/3*15/4-(-(1/2)/(1/2))/(1421+(1+23)/2)))))))"};
	private final ExpressionParser parser = new ExpressionParser();
	
	//string value = com.google.gwt.user.client.Window.Location.getParameter("orderId");

	
	/**
	   * Add term to FlexTable. Executed when the user clicks the addTermButton or
	   * presses enter in the newSymbolTextBox.
	   */
	  private void addTerm() {    
		  final String symbol = newSymbolTextBox.getText().trim();
		  Term term = null;
	      Vector<Surface> surface = new Vector<Surface>();
		  String result;
		  
		// NumberTerm must be between 0 and 9 chars that are numbers.
		  
		  /*if (!symbol.matches("^-?[0-9]+$")) {	Window.alert("'" + symbol + "' is not a valid NumberTerm.");
			  newSymbolTextBox.selectAll();
			  return;
		  } else {*/
			  try {
				  term = parser.parseText(symbol);
				  result = term.toString();
					
					for (String font : fonts) {
						TermRenderer.setFont(font);
						surface.add(TermRenderer.renderCanvas(term));
					}
			  } catch (ExpressionParserException e) {
				  term = null;
				  Integer row = termTable.getRowCount() + 1;
				  termTable.setText(row, 0, symbol);
				  termTable.setText(row, 1, "error while parsing text");
				  termTable.setText(row, 2, "-");
				  termTable.setText(row, 3, "-");
				  termTable.setText(row, 4, "-");
				  return;
			  } catch (TermRendererException e) {
				  e.printStackTrace();
				  
				  Integer row = termTable.getRowCount() + 1;
				  termTable.setText(row, 0, symbol);
				  if (term!=null) termTable.setText(row, 1, term.toString());
				  termTable.setText(row, 2, "error while rendering term");
				  termTable.setText(row, 3, "error while rendering term");
				  termTable.setText(row, 4, "error while rendering term");
				  return;
			  }		  
		  
		  newSymbolTextBox.setFocus(true);

		  // TODO Add the term to the table.
		  if (term != null) {
			Integer rows = termTable.getRowCount();
			Integer row = rows+1;
			termTable.setText(row, 0, symbol);
			termTable.setText(row, 1, result);
			termTable.setWidget(row, 2, surface.elementAt(0));
			termTable.setWidget(row, 3, surface.elementAt(1));
			termTable.setWidget(row, 4, surface.elementAt(2));	
		  }
		 
		  newSymbolTextBox.setText("");
		  // TODO Add a button to remove this term from the table.

		  // TODO Get the stock price.

	  }
	
	/**
	 * This is the entry point method.
	 */
	public VerticalPanel getPanel() {
	    // Assemble Add Stock panel.
	    addPanel.add(newSymbolTextBox);
	    addPanel.add(addTermButton);
		
	    // Assemble Main panel.
	    mainPanel.add(termTable);
	    mainPanel.add(addPanel);
	    

	    

	    // Move cursor focus to the input box.
	    newSymbolTextBox.setFocus(true);
	    
		termTable.setText(0, 0, "Expression");
		termTable.setText(0, 1, "Term.toString()");
		termTable.setText(0, 2, fonts[0]);
		termTable.setText(0, 3, fonts[1]);
		termTable.setText(0, 4, fonts[2]);
		
		String result = null;
		for (String expression : fractionExpressions) {
			Vector<Surface> surface = new Vector<Surface>();
			try {
				Term term = parser.parseText(expression);
				result = term.toString();
				
				for (String font : fonts) {
					TermRenderer.setFont(font);
					surface.add(TermRenderer.renderCanvas(term));
				}
			} catch (TermRendererException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExpressionParserException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			Integer rows = termTable.getRowCount();
			Integer row = rows+1;
			termTable.setText(row, 0, expression);
			termTable.setText(row, 1, result);
			termTable.setWidget(row, 2, surface.elementAt(0));
			termTable.setWidget(row, 3, surface.elementAt(1));
			termTable.setWidget(row, 4, surface.elementAt(2));
		}
		
		// Listen for mouse events on the Add button.
	    addTermButton.addClickHandler(new ClickHandler() {
	      public void onClick(ClickEvent event) {
				addTerm();
	      }  
	    });
	    
	 // Listen for keyboard events in the input box.
	    newSymbolTextBox.addKeyPressHandler(new KeyPressHandler() {
	      public void onKeyPress(KeyPressEvent event) {
	        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
				addTerm();
			}
	      }
	    });
	    
	    return mainPanel;
	}
}
